package org.javaforever.cookieshop.serviceimpl;

import java.sql.SQLException;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.javaforever.cookieshop.dao.RoleDao;
import org.javaforever.cookieshop.dao.UserDao;
import org.javaforever.cookieshop.domain.PageBean;
import org.javaforever.cookieshop.domain.RoleBean;
import org.javaforever.cookieshop.domain.UserBean;
import org.javaforever.cookieshop.service.RoleService;
import org.javaforever.cookieshop.service.UserService;
import org.javaforever.cookieshop.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;

@Service
public class UserServiceImpl implements UserService{
	@Autowired
	protected UserDao dao;

	@Autowired
	protected RoleDao roleDao;

	@Autowired
	protected RoleService roleService;
	@PersistenceContext
	protected EntityManager entityManager;

	@Override
	public void activateAllUsers(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.activateUser(id);
        }
	}

	@Override
	public Boolean activateUser(Long id) throws Exception{
        dao.activateUser(id);
        return true;
	}

	@Override
	@Transactional
	public Boolean addUser(UserBean user) throws Exception{
        dao.saveAndFlush(user);
        return true;
	}

	@Override
	@Transactional
	public Boolean assignRolesToUser(Long userId,String roleIds) throws Exception{
        String [] roleIdsArr = roleIds.split(",");
        for (int i = 0; i < roleIdsArr.length; i++ ){
        Long roleId = Long.parseLong(roleIdsArr[i]);
        Integer success = dao.assignRoleToUser(userId,roleId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	@Transactional
	public Boolean changePasswordUser(UserBean user) throws Exception{
        entityManager.merge(user);
        return true;
	}

	@Override
	public void cloneAllUsers(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            cloneUser(id);
        }
	}

	@Override
	public Boolean cloneUser(Long id) throws Exception{
        UserBean user = dao.findUserFullInfoById(id);
        
        String userName = user.getUserName();
        String shortName = userName;
        if (userName.contains("_") && StringUtil.isInteger(userName.substring(userName.lastIndexOf('_')+1,userName.length()))) {
            shortName = userName.substring(0,userName.lastIndexOf('_'));
        }
        List<UserBean> names = dao.searchUserIndexedNamesByShortName(shortName);
        int indexNum = 1;
        for (UserBean user0:names) {
            String _name = user0.getUserName();
            if (_name.contains("_") && StringUtil.isInteger(_name.substring(_name.lastIndexOf('_')+1,_name.length()))) {
                int index = Integer.valueOf(_name.substring(_name.lastIndexOf('_')+1,_name.length()));
                if (index >= indexNum) {
                    indexNum = index + 1;
                }
            }
        }
        String indexName = shortName + "_" + indexNum;
        UserBean user1 = user.clone();
        user1.setId(null);
        user1.setUserName(indexName);
        addUser(user1);
        return true;
	}

	@Override
	public Integer countActiveUserRecords() throws Exception{
        return dao.countActiveUserRecords();
	}

	@Override
	public Integer countSearchUsersByFieldsRecords(UserBean user) throws Exception{
        String jpql = "select count(*) as countNum from UserBean u where 1=1 ";
        if (user.getUserName() != null) {
            jpql += " and u.userName like CONCAT('%', '"+user.getUserName()+"','%')";
        }
        if (user.getActive() != null) {
            jpql += " and u.active = "+user.getActive();
        }
        if (user.getFirstName() != null) {
            jpql += " and u.firstName like CONCAT('%', '"+user.getFirstName()+"','%')";
        }
        if (user.getLastName() != null) {
            jpql += " and u.lastName like CONCAT('%', '"+user.getLastName()+"','%')";
        }
        if (user.getEmail() != null) {
            jpql += " and u.email like CONCAT('%', '"+user.getEmail()+"','%')";
        }
        if (user.getIsadmin() != null) {
            jpql += " and u.isadmin = "+user.getIsadmin();
        }
        if (user.getGender() != null) {
            jpql += " and u.gender like CONCAT('%', '"+user.getGender()+"','%')";
        }
        if (user.getAddress() != null) {
            jpql += " and u.address like CONCAT('%', '"+user.getAddress()+"','%')";
        }
        if (user.getPhone() != null) {
            jpql += " and u.phone like CONCAT('%', '"+user.getPhone()+"','%')";
        }
        if (user.getDescription() != null) {
            jpql += " and u.description like CONCAT('%', '"+user.getDescription()+"','%')";
        }
        Query query = entityManager.createQuery(jpql);
        Long count = (Long) query.getSingleResult();
        return count.intValue();
	}

	@Override
	public Integer countUserByUserName(String userName) throws Exception{
        return dao.countUserByUserName(userName);
	}

	@Override
	public void deleteAllUsers(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.deleteUser(id);
        }
	}

	@Override
	public Boolean deleteUser(Long id) throws Exception{
        dao.deleteUser(id);
        return true;
	}

	@Override
	public UserBean findUserById(Long id) throws Exception{
        return dao.findUserById(id);
	}

	@Override
	public UserBean findUserByUserName(String userName) throws Exception{
        return dao.findUserByUserName(userName);
	}

	@Override
	public String getPasswordUser(String userName) throws Exception{
        return dao.getPasswordUser(userName);
	}

	@Override
	public String getSaltUser(String userName) throws Exception{
        return dao.getSaltUser(userName);
	}

	@Override
	public Set<RoleBean> listActiveUserRolesUsingUserId(Long userId) throws Exception{
        Set<RoleBean> _set = new TreeSet<RoleBean>();
        _set.addAll(roleDao.listActiveUserRolesUsingUserId(userId));
        return _set;
	}

	@Override
	public List<UserBean> listActiveUsers() throws Exception{
        return dao.listActiveUsers();
	}

	@Override
	public List<UserBean> listAllUsers() throws Exception{
        return dao.listAllUsers();
	}

	@Override
	public Set<RoleBean> listAvailableActiveUserRolesUsingUserId(Long userId) throws Exception{
        Set<RoleBean> fullset = new TreeSet<RoleBean>();
        fullset.addAll(roleService.listActiveRoles());
        Set<RoleBean> set = listActiveUserRolesUsingUserId(userId);
        fullset.removeAll(set);	
        return fullset;
	}

	@Override
	@Transactional
	public Boolean registerUser(UserBean user) throws Exception{
        dao.saveAndFlush(user);
        return true;
	}

	@Override
	@Transactional
	public Boolean revokeRolesFromUser(Long userId,String roleIds) throws Exception{
        String [] roleIdsArr = roleIds.split(",");
        for (int i = 0; i < roleIdsArr.length; i++ ){
        Long roleId = Long.parseLong(roleIdsArr[i]);
        Integer success = dao.revokeRoleFromUser(userId,roleId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	public List<UserBean> searchUsersByFields(UserBean user) throws Exception{
        String jpql = "from UserBean u where 1=1 ";
        if (user.getUserName() != null) {
            jpql += " and u.userName like CONCAT('%', '"+user.getUserName()+"','%')";
        }
        if (user.getActive() != null) {
            jpql += " and u.active = "+user.getActive();
        }
        if (user.getFirstName() != null) {
            jpql += " and u.firstName like CONCAT('%', '"+user.getFirstName()+"','%')";
        }
        if (user.getLastName() != null) {
            jpql += " and u.lastName like CONCAT('%', '"+user.getLastName()+"','%')";
        }
        if (user.getEmail() != null) {
            jpql += " and u.email like CONCAT('%', '"+user.getEmail()+"','%')";
        }
        if (user.getIsadmin() != null) {
            jpql += " and u.isadmin = "+user.getIsadmin();
        }
        if (user.getGender() != null) {
            jpql += " and u.gender like CONCAT('%', '"+user.getGender()+"','%')";
        }
        if (user.getAddress() != null) {
            jpql += " and u.address like CONCAT('%', '"+user.getAddress()+"','%')";
        }
        if (user.getPhone() != null) {
            jpql += " and u.phone like CONCAT('%', '"+user.getPhone()+"','%')";
        }
        if (user.getDescription() != null) {
            jpql += " and u.description like CONCAT('%', '"+user.getDescription()+"','%')";
        }
        Query query = entityManager.createQuery(jpql);
        List<UserBean> results = query.getResultList();
        return results;
	}

	@Override
	public List<UserBean> searchUsersByFieldsByPage(UserBean user,Integer pagesize,Integer pagenum) throws Exception{
        Integer start = (pagenum-1)*pagesize;
        Integer limit = pagesize;
        String jpql = "from UserBean u where 1=1 ";
        if (user.getUserName() != null) {
            jpql += " and u.userName like CONCAT('%', '"+user.getUserName()+"','%')";
        }
        if (user.getActive() != null) {
            jpql += " and u.active = "+user.getActive();
        }
        if (user.getFirstName() != null) {
            jpql += " and u.firstName like CONCAT('%', '"+user.getFirstName()+"','%')";
        }
        if (user.getLastName() != null) {
            jpql += " and u.lastName like CONCAT('%', '"+user.getLastName()+"','%')";
        }
        if (user.getEmail() != null) {
            jpql += " and u.email like CONCAT('%', '"+user.getEmail()+"','%')";
        }
        if (user.getIsadmin() != null) {
            jpql += " and u.isadmin = "+user.getIsadmin();
        }
        if (user.getGender() != null) {
            jpql += " and u.gender like CONCAT('%', '"+user.getGender()+"','%')";
        }
        if (user.getAddress() != null) {
            jpql += " and u.address like CONCAT('%', '"+user.getAddress()+"','%')";
        }
        if (user.getPhone() != null) {
            jpql += " and u.phone like CONCAT('%', '"+user.getPhone()+"','%')";
        }
        if (user.getDescription() != null) {
            jpql += " and u.description like CONCAT('%', '"+user.getDescription()+"','%')";
        }
        Query query = entityManager.createQuery(jpql);
        query.setFirstResult(start); // 设置起始位置
        query.setMaxResults(limit); // 设置返回结果数量
        List<UserBean> results = query.getResultList();
        return results;
	}

	public void setDao(UserDao dao){
		this.dao = dao;
	}

	public void setRoleService(RoleService roleService){
		this.roleService = roleService;
	}

	@Override
	public void softDeleteAllUsers(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.softDeleteUser(id);
        }
	}

	@Override
	public boolean softDeleteUser(Long id) throws Exception{
        dao.softDeleteUser(id);
        return true;
	}

	@Override
	public Boolean toggleOneUser(Long id) throws Exception{
        UserBean user = dao.findUserById(id);
        if (user.getActive()==false) {
            dao.toggleUser(id);
        }
        else {
            Integer count = dao.countActiveUserRecords();
            if (count > 1){
                dao.toggleUser(id);
            }
        }
        return true;
	}

	@Override
	public Boolean toggleUser(Long id) throws Exception{
        dao.toggleUser(id);
        return true;
	}

	@Override
	@Transactional
	public Boolean updateUser(UserBean user) throws Exception{
        entityManager.merge(user);
        return true;
	}

	@Override
	public PageBean getUserPage(int pageNumber) throws Exception{
        PageBean p = new PageBean();
        p.setPageNumber(pageNumber);
        int pageSize = 7;
        int totalCount = dao.countActiveUserRecords();
        p.SetPageSizeAndTotalCount(pageSize, totalCount);
        List list=null;
        list = dao.listActiveUsers();
    	Integer start = (pageNumber-1)*pageSize;
    	Integer limit = pageSize;
    	Integer end = start + limit < totalCount ? start + limit : totalCount;
        p.setList(list.subList(start, end));
        return p;
    }
}
